home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_dos.lha / dos / sphsrc / sph_zsor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  18.4 KB  |  728 lines

  1. #include "HEADERS.h"
  2.  
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include "sphigslocal.h"
  6.  
  7. static void sort( );
  8. static void correct( );
  9. static int test_point( );
  10. static int test_relation( );
  11. static void compute_plane_equation( );
  12. static int test_point( );
  13. static boolean xy_extent_intersect( );
  14. static boolean test_lines( );
  15. static boolean get_index_line( );
  16. static boolean test_proj_intersect( );
  17. static void perspect_bound( );
  18. static void interpolate_3d_point( );
  19. static void split( );
  20.  
  21.  
  22. void bound(view_spec *vs, obj *current );
  23. vertex_index add_global_point(view_spec *vs, MAT3hvec p );
  24.  
  25.  
  26. void
  27. SPH__zsort( vs )
  28.      view_spec *    vs;
  29. {
  30.      obj *        list;
  31.      obj *        sorted_list;        /* list sorted from back to front */
  32.      obj *        current;
  33.      obj *        prev;
  34.      obj *        next_object;
  35.      
  36.      assert( vs != NULL );
  37.      
  38.      if( vs->objects != NULL )
  39.       sort( vs );
  40.      
  41.      if( vs->objects != NULL )
  42.       correct( vs );
  43. }
  44.  
  45.  
  46. static void
  47. sort( vs )
  48.      view_spec *    vs;
  49. {
  50.      obj *        list;
  51.      obj *        sorted_list;        /* list sorted from back to front */
  52.      obj *        current;
  53.      obj *        prev;
  54.      obj *        next_object;
  55.      
  56.      assert( vs != NULL );
  57.      list = vs->objects;
  58.      
  59.      sorted_list = NULL;
  60.      while( list != NULL ) {            /* take the top object of the list */
  61.       
  62.       compute_plane_equation( vs, list );
  63.       list->already_moved = FALSE;
  64.       
  65.       prev = NULL;
  66.       current = sorted_list;
  67.       
  68.       /* search in the new list for the place to put it */
  69.       
  70.       while( current != NULL && list->min[Z] > current->min[Z] ) {
  71.            prev = current;
  72.            assert( current != current->next );
  73.            current = current->next;
  74.       }
  75.       
  76.       if( prev == NULL )
  77.            sorted_list = list;
  78.       else
  79.            prev->next = list;
  80.       
  81.       next_object = list->next;
  82.       assert( next_object != list );
  83.       list->next = current;
  84.       
  85.       list = next_object;
  86.       
  87.      }
  88.      
  89.      vs->objects = sorted_list;
  90. }
  91.  
  92.  
  93. static void
  94. correct( vs )
  95.      view_spec *    vs;
  96. {
  97.      obj *        list;
  98.      obj *        current_prev;
  99.      obj *        current;
  100.      obj *        current_next;
  101.      obj *        scan_prev;
  102.      obj *        scan;
  103.      obj *        scan_next;
  104.      int        relation1, relation2;
  105.      obj        swap;
  106.      
  107.      assert( vs != NULL );
  108.      
  109.      list = vs->objects;
  110.      
  111.      current = list;
  112.      current_prev = NULL;
  113.      while( current != NULL ) {
  114. here:      
  115.       scan = current->next;
  116.       scan_prev = current;
  117.       while( scan != NULL && scan->min[Z] <= current->max[Z] ) {
  118.            
  119. /*           fprintf( stderr, "checking %d %d %d   %d %d %d\n", scan->data.face.points[0], scan->data.face.points[1], scan->data.face.points[2], current->data.face.points[0], current->data.face.points[1], current->data.face.points[2] ); */
  120.            
  121.            if( ! xy_extent_intersect( current, scan ) ) {
  122.             scan_prev = scan;
  123.             scan = scan->next;
  124.             continue;
  125.            }
  126.            relation1 = test_relation( current, scan, vs );
  127.            if( relation1 == -1 ) {
  128.             scan_prev = scan;
  129.             scan = scan->next;
  130.             continue;
  131.            }
  132.            relation2 = test_relation( scan, current, vs );
  133.            if( relation2 == 1 ) {
  134.             scan_prev = scan;
  135.             scan = scan->next;
  136.             continue;
  137.            }
  138.            
  139.            if( relation1 == relation2 == 0 ) {
  140.             /* HORRORS! a pair of intersecting polygons! */
  141.             /* split( current, scan, scan_prev, vs ); */
  142.             /*********scan_prev = scan;            SKLAR added as a guess*/
  143.             /*********scan = scan->next;    SKLAR added as a guess*/
  144.             /* continue; */  /*SKLAR commented out as a guess*/
  145.            }
  146.            
  147.            if( ! test_proj_intersect( scan, current, vs ) ) {
  148.             scan_prev = scan;
  149.             scan = scan->next;
  150.             continue;
  151.            }
  152.            
  153.            if( current->already_moved ) {
  154.             scan_prev = scan;
  155.             scan = scan->next;
  156.             continue;
  157.            }
  158.            
  159.            current_next = current->next;
  160.            scan_next = scan->next;
  161.            
  162. /*           fprintf (stderr, "swapping..\n");
  163.             current->attributes.interior_color = 7;
  164.             scan->attributes.interior_color = 7; */
  165.            
  166. /*           fprintf (stderr, 
  167.                     "before swap c %x s %x cp %x sp %x cn %x sn %x\n", 
  168.             (long) current, (long) scan,
  169.             (long) current_prev, (long) scan_prev, 
  170.             (long) current_next, (long) scan_next ); */
  171.            
  172.            swap = *scan;                /* the easy swap */
  173.            *scan = *current;
  174.            *current = swap;
  175.            
  176.            current->next = current_next;
  177.            scan->next = scan_next;
  178.            
  179.            scan->already_moved = TRUE;
  180.  
  181.  
  182. /*           if( scan == current->next ) {        * we are reordering two consecutive nodes *
  183.             
  184.             fprintf( stderr, "ah its seq!\n" );
  185.             if( current_prev != NULL )
  186.              current_prev->next = scan;
  187.             else
  188.              list = scan;
  189.             scan->next = current;
  190.             current->next = scan_next;
  191.             
  192.             current = scan;
  193.             
  194.            } else {                    * two arbitrary nodes *
  195.             
  196.            * fix the previous node *
  197.             
  198.             if( current_prev != NULL )
  199.              current_prev->next = scan;
  200.             else
  201.              list = scan;
  202.             scan->next = current_next;
  203.             
  204.             scan_prev->next = current;
  205.             current->next = scan_next;
  206.             
  207.             current = scan;
  208.            }
  209. */           
  210.  
  211. /*           fprintf (stderr, 
  212.                     "after swap c %x s %x cp %x sp %x cn %x sn %x\n", 
  213.             (long) current, (long) scan,
  214.             (long) current_prev, (long) scan_prev, 
  215.             (long) current_next, (long) scan_next ); */
  216.            
  217.            /* restart this level of scanning */
  218.            
  219.            goto here;
  220.       }
  221.       
  222.       current_prev = current;
  223.       current = current->next;
  224.      }
  225.      
  226.      vs->objects = list;
  227. }
  228.  
  229.  
  230. static void
  231. compute_plane_equation( vs, current )
  232.      view_spec *    vs;
  233.      obj *              current;
  234. {
  235.      MAT3hvec        p;
  236.      MAT3hvec        normal;
  237.      double        length;
  238.      
  239.      assert( current != NULL );
  240.      assert( vs != NULL );
  241.      assert( vs->npcVertices != NULL );
  242.      
  243.      perspect_bound( vs, current );
  244.      
  245.      switch( current->type ) {
  246.     case objFace:
  247.       MAT3_COPY_VEC( p, vs->npcVertices[ current->data.face.points[0] ] );
  248.       MAT3_COPY_VEC( normal, current->p_normal );
  249.       current->directed_distance = - ( normal[X] * p[X] + normal[Y] * p[Y] + normal[Z] * p[Z] );
  250.       break;
  251.       
  252.     case objText:
  253.       current->p_normal[3] = 1;
  254.       MAT3_NORMALIZE_VEC( current->p_normal, length );
  255.       current->directed_distance = - ( current->min[Z] );
  256.       break;
  257.       
  258.     case objLine:
  259.       MAT3_COPY_VEC( p, current->data.line.end1 );
  260.       normal[X] = - ( current->data.line.end1[Z] - current->data.line.end2[Z] );
  261.       normal[Y] = 0;
  262.       normal[Z] = - ( current->data.line.end1[X] - current->data.line.end2[X] );
  263.       normal[3] = 1;
  264.       MAT3_NORMALIZE_VEC( normal, length );
  265.       current->directed_distance = - ( normal[X] * current->data.line.end1[X] +
  266.                       normal[Z] * current->data.line.end1[Z] );
  267.       MAT3_COPY_VEC( current->normal, normal );
  268.       break;
  269.       
  270.     case objPoint:
  271.       break;
  272.      }
  273. }
  274.  
  275.  
  276. /**********************
  277.                       *
  278.  Function          * perspect_bound
  279.                       *
  280.                       * calculates the bounding cube for the object
  281.                       *
  282.                       *********************************************************/
  283.  
  284. static void
  285. perspect_bound( vs, current )
  286.      view_spec *        vs;
  287.      obj *        current;
  288. {
  289.      int        index;
  290.      MAT3hvec        p;
  291.      MAT3hvec        max;
  292.      MAT3hvec        min;
  293.      
  294.      assert( vs != NULL );
  295.      assert( vs->npcVertices != NULL );
  296.      assert( current != NULL );
  297.      
  298.      assert( current->type == objFace );
  299.      
  300.      switch( current->type ) {
  301.     case objFace:
  302.       
  303.       max[X] = max[Y] = -HUGE_VAL;
  304.       min[X] = min[Y] = HUGE_VAL;
  305.       
  306.       for( index = 0; index < current->data.face.numPoints; index++ ) {
  307.            MAT3_COPY_VEC( p, (vs->npcVertices)[ current->data.face.points[ index ] ] );
  308.            if( p[X] > max[X] )
  309.             max[X] = p[X];
  310.            if( p[Y] > max[Y] )
  311.             max[Y] = p[Y];
  312.            
  313.            if( p[X] < min[X] )
  314.             min[X] = p[X];
  315.            if( p[Y] < min[Y] )
  316.             min[Y] = p[Y];
  317.       }
  318.       
  319.       MAT3_COPY_VEC( current->p_min, min );
  320.       MAT3_COPY_VEC( current->p_max, max );
  321.       
  322.       break;
  323.      }
  324.   }
  325.  
  326. /**********************
  327.                       *
  328.  Function          * xy_extent_intersect
  329.                       *
  330.               * returns TRUE if the x-y bounds intersect
  331.               *
  332.                       *********************************************************/
  333.  
  334. static boolean
  335. xy_extent_intersect( obj1, obj2 )
  336.      obj *        obj1;
  337.      obj *        obj2;
  338. {
  339.  
  340.      MAT3hvec        obj2_p_min, obj2_p_max;
  341.      boolean        x_intersect;
  342.      boolean        y_intersect;
  343.      
  344.      MAT3_COPY_VEC( (double *) obj2_p_min, (double *) obj2->p_min );
  345.      MAT3_COPY_VEC( (double *) obj2_p_max, (double *) obj2->p_max );
  346.      
  347.      x_intersect = ( obj1->p_min[X] >= obj2_p_min[X] && obj1->p_min[X] < obj2_p_max[X] ) |
  348.       ( obj1->p_max[X] > obj2_p_min[X] && obj1->p_max[X] <= obj2_p_max[X] );
  349.      y_intersect = ( obj1->p_min[Y] >= obj2_p_min[Y] && obj1->p_min[Y] < obj2_p_max[Y] ) |
  350.       ( obj1->p_max[Y] > obj2_p_min[Y] && obj1->p_max[Y] <= obj2_p_max[Y] );
  351.      return( x_intersect & y_intersect );
  352. /*
  353.      MAT3hvec        obj2_min, obj2_max;
  354.      boolean        x_intersect;
  355.      boolean        y_intersect;
  356.      
  357.      MAT3_COPY_VEC( (double *) obj2_min, (double *) obj2->min );
  358.      MAT3_COPY_VEC( (double *) obj2_max, (double *) obj2->max );
  359.      
  360.      x_intersect = ( obj1->min[X] >= obj2_min[X] && obj1->min[X] < obj2_max[X] ) |
  361.       ( obj1->max[X] > obj2_min[X] && obj1->max[X] <= obj2_max[X] );
  362.      y_intersect = ( obj1->min[Y] >= obj2_min[Y] && obj1->min[Y] < obj2_max[Y] ) |
  363.       ( obj1->max[Y] > obj2_min[Y] && obj1->max[Y] <= obj2_max[Y] );
  364.      return( x_intersect & y_intersect );
  365. */
  366. }
  367.  
  368. /**********************
  369.                       *
  370.  Function          * test_relation
  371.                       *
  372.               * returns -1 if obj1 is outside obj2
  373.               * returns  0 if obj1 is intersecting obj2
  374.               * returns  1 if obj1 is inside obj2
  375.               *    
  376.               *    tests each point in obj1 against the plane equation of
  377.               *       obj2
  378.               *    
  379.                       *********************************************************/
  380.  
  381. static int
  382. test_relation( obj1, obj2, vs )
  383.      obj *        obj1;
  384.      obj *        obj2;
  385.      view_spec *    vs;
  386. {
  387.      MAT3hvec             obj1_point;
  388.      MAT3hvec        obj2_normal;
  389.      int        index;
  390.      int        relation;            /* relation of first point of obj1 to obj2; the relation to match */
  391.      int        new_relation;            /* the relation of each other point of obj1 */
  392.      double        plane_point;            /* each point of the plane obj1 */
  393.      
  394.      assert( vs != NULL );
  395.      assert( vs->npcVertices != NULL );
  396.      assert( obj1 != NULL );
  397.      assert( obj2 != NULL );
  398.      
  399.      switch( obj1->type ) {
  400.       
  401.       /******* face *******/
  402.       
  403.     case objFace:
  404.       
  405.       index = 0;
  406.       
  407.       MAT3_COPY_VEC( obj2_normal, obj2->p_normal );
  408.       
  409.       MAT3_COPY_VEC( obj1_point, (vs->npcVertices)[ obj1->data.face.points[ index ] ] );
  410.       relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  411.       
  412.       for( index = 1; index < obj1->data.face.numPoints; index++ ) {
  413.            
  414.            MAT3_COPY_VEC( obj1_point, (vs->npcVertices)[ obj1->data.face.points[ index ] ] );
  415.            new_relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  416.            
  417.            /* check for intersecting between faces */
  418.            
  419.            if( relation == 0 && new_relation != 0 )
  420.             relation = new_relation;
  421.            
  422.            if( new_relation != relation && new_relation + relation == 0 )
  423.             return( 0 );
  424.       }
  425.       return( relation );
  426.       break;
  427.       
  428.       /******* text *******/
  429.       
  430.     case objText:
  431.       MAT3_COPY_VEC( obj2_normal, obj2->p_normal );
  432.       
  433.       obj1_point[Z] = obj1->min[Z];
  434.       
  435.       obj1_point[X] = obj1->min[X];
  436.       obj1_point[Y] = obj1->min[Y];
  437.       relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  438.       
  439.       obj1_point[X] = obj1->min[X];
  440.       obj1_point[Y] = obj1->max[Y];
  441.       new_relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  442.       if( relation != new_relation )
  443.            return( 0 );
  444.       
  445.       obj1_point[X] = obj1->max[X];
  446.       obj1_point[Y] = obj1->min[Y];
  447.       new_relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  448.       if( relation != new_relation )
  449.            return( 0 );
  450.       
  451.       obj1_point[X] = obj1->max[X];
  452.       obj1_point[Y] = obj1->max[Y];
  453.       new_relation = test_point( obj1_point, obj2_normal, obj2->directed_distance );
  454.       if( relation != new_relation )
  455.            return( 0 );
  456.       
  457.       return( relation );
  458.       break;
  459.       
  460.       /******* line *******/
  461.       
  462.     case objLine:
  463.       MAT3_COPY_VEC( obj2_normal, obj2->normal );
  464.       
  465.       MAT3_COPY_VEC( obj1_point, obj1->data.line.end1 );
  466.       relation = test_point( obj1_point, obj2->normal, obj2->directed_distance );
  467.       
  468.       MAT3_COPY_VEC( obj1_point, obj1->data.line.end2 );
  469.       new_relation = test_point( obj1_point, obj2->normal, obj2->directed_distance );
  470.       if( relation != new_relation )
  471.            return( 0 );
  472.       
  473.       return( relation );
  474.       break;
  475.       
  476.     case objPoint:
  477.       MAT3_COPY_VEC( obj2_normal, obj2->normal );
  478.       
  479.       relation = test_point( obj1->min, obj2->normal, obj2->directed_distance );
  480.       return( relation );
  481.      }
  482. }
  483.  
  484. /**********************
  485.                       *
  486.  Function          * test_point
  487.                       *
  488.               * returns -1 if p is behind plane with normal
  489.               * returns  0 if p is on plane with normal
  490.               * returns  1 if p is in front of plane with normal
  491.               *    
  492.                       *********************************************************/
  493.  
  494. static int
  495. test_point( p, normal, distance )
  496.      MAT3hvec            p;
  497.      MAT3hvec            normal;
  498.      double            distance;
  499. {
  500.      double            plane_point;
  501.      
  502.      plane_point = normal[X] * p[X] + normal[Y] * p[Y] + normal[Z] * p[Z] + distance;
  503.      if( normal[Z] > 0 ) {
  504.       if( plane_point < -1e-4 )
  505.            return( -1 );
  506.       else if( plane_point > 1e-4 )
  507.            return( 1 );
  508.       else
  509.            return( 0 );
  510.      } else {
  511.       if( plane_point < -1e-4 )
  512.            return( 1 );
  513.       else if( plane_point > 1e-4 )
  514.            return( -1 );
  515.       else
  516.            return( 0 );
  517.      }
  518. }
  519.  
  520. /**********************
  521.                       *
  522.  Function          * test_proj_intersect
  523.                       *
  524.               * returns TRUE if the projections intersect
  525.               *    a brutal n^2 approach
  526.               *
  527.                       *********************************************************/
  528.  
  529. static boolean
  530. test_proj_intersect( obj1, obj2, vs )
  531.      obj *        obj1;
  532.      obj *        obj2;
  533.      view_spec *    vs;
  534. {
  535.      int        end1;
  536.      int        end2;
  537.      int        endA;
  538.      int        endB;
  539.      int        i, j;
  540.      int        old_cw;
  541.      int        last;
  542.      int        cw;
  543.      boolean        same;
  544.      
  545.      assert( vs != NULL );
  546.      assert( obj1 != NULL );
  547.      assert( obj2 != NULL );
  548.      
  549. /*     last = -1;
  550.      same = TRUE;
  551.      for( i = 0; i < obj1->data.face.numPoints; i++ ) {
  552.       get_index_line( obj2, i, &end1, &end2 );
  553.       cw = ccw( obj1->data.face.points[ i ], end1, end2, vs );
  554.       if( last == -1 ) {
  555.            old_cw = cw;
  556.            last = 0;
  557.       } else {
  558.            same = same & ( cw == old_cw );
  559.       }
  560.      }
  561.      if( same )
  562.       return( TRUE );
  563.      
  564.      last = -1;
  565.      same = TRUE;
  566.      for( i = 0; i < obj2->data.face.numPoints; i++ ) {
  567.       get_index_line( obj1, i, &end1, &end2 );
  568.       cw = ccw( obj2->data.face.points[ i ], end1, end2, vs );
  569.       if( last == -1 ) {
  570.            old_cw = cw;
  571.            last = 0;
  572.       } else {
  573.            same = same & ( cw == old_cw );
  574.       }
  575.      }
  576.      if( same )
  577.       return( TRUE );
  578.      */
  579.      
  580.      assert( vs != NULL );
  581.      
  582.      i = 0;
  583.      while( get_index_line( obj1, i, &end1, &end2 ) ) {
  584.       j = 0;
  585.       while( get_index_line( obj2, j, &endA, &endB ) ) {
  586.            if( test_lines( end1, end2, endA, endB, vs ) ) {
  587.             return( TRUE );
  588.            }
  589.            j ++;
  590.       }
  591.       i ++;
  592.      }
  593.      return( FALSE );
  594. }
  595.  
  596. /**********************
  597.                       *
  598.  Function          * ccw
  599.                       *
  600.                       *********************************************************/
  601.  
  602. static int
  603. ccw( end0, end1, end2, vs )
  604.      int        end0;
  605.      int        end1;
  606.      int        end2;
  607.      view_spec *    vs;
  608. {
  609.      MAT3hvec *        npcVertices;
  610.      double        dx1, dx2, dy1, dy2;
  611.      
  612.      assert( vs != NULL );
  613.      
  614.      assert( vs->npcVertices != NULL );
  615.      npcVertices = vs->npcVertices;
  616.      
  617.      dx1 = (npcVertices[end1])[X] - (npcVertices[end0])[X];
  618.      dy1 = (npcVertices[end1])[Y] - (npcVertices[end0])[Y];
  619.      dx2 = (npcVertices[end2])[X] - (npcVertices[end0])[X];
  620.      dy2 = (npcVertices[end2])[Y] - (npcVertices[end0])[Y];
  621.      
  622.      if( dx1 * dy2 > dy1 * dx2 )
  623.       return( 1 );
  624.      else if( dx1 * dy2 < dy1 * dx2 )
  625.       return( -1 );
  626.      else
  627.       return( 0 );
  628. }
  629.  
  630. /**********************
  631.                       *
  632.  Function          * test_lines
  633.                       *
  634.               * returns TRUE if the lines intersect
  635.               *
  636.                       *********************************************************/
  637.  
  638. static boolean
  639. test_lines( end1, end2, endA, endB, vs )
  640.      int        end1;
  641.      int        end2;
  642.      int        endA;
  643.      int        endB;
  644.      view_spec  *vs;
  645. {
  646.      assert( vs != NULL );
  647.      
  648.      if( ( end1 == endA && end2 == endB ) || ( end1 == endB && end2 == endA ) ) {
  649.       return( FALSE );
  650.      }
  651.      
  652.      return( ( ccw( end1, end2, endA, vs ) * ccw( end1, end2, endB, vs ) < 0 ) &&
  653.         ( ccw( endA, endB, end1, vs ) * ccw( endA, endB, end2, vs ) < 0 ) );
  654. }
  655.  
  656. /**********************
  657.                       *
  658.  Function          * get_index_line
  659.                       *
  660.               * returns FALSE if the index is out of bounds
  661.               *
  662.                       *********************************************************/
  663.  
  664. static boolean
  665. get_index_line( obj1, index, end1, end2 )
  666.      obj *        obj1;
  667.      int        index;
  668.      int *         end1;
  669.      int *        end2;
  670. {
  671.      vertex_index *    points;
  672.      
  673.      assert( end1 != NULL );
  674.      assert( end2 != NULL );
  675.      assert( obj1 != NULL );
  676.      
  677.      assert( obj1->type == objFace );        /* for now */
  678.      
  679.      switch( obj1->type ) {
  680.     case objFace:
  681.       points = obj1->data.face.points;
  682.       if( index >= obj1->data.face.numPoints )
  683.            return( FALSE );
  684.       *end1 = points[ index ];
  685.       if( index == obj1->data.face.numPoints - 1 )
  686.            *end2 = points[ 0 ];
  687.       else
  688.            *end2 = points[ index + 1 ];
  689.       break;
  690.     case objText:
  691.       break;
  692.     case objLine:
  693.       break;
  694.     case objPoint:
  695.       break;
  696.      }
  697.      return( TRUE );
  698. }
  699.  
  700.  
  701.  
  702.  
  703. /**********************
  704.                       *
  705.  Function          * interpolate_3d_points
  706.                       *
  707.                       *********************************************************/
  708.  
  709. static void
  710. interpolate_3d_point( start, end, obj1, new )
  711.      obj *        obj1;
  712.      MAT3hvec        start, end, new;
  713. {
  714.      double        p;
  715.      MAT3hvec        slope;
  716.      
  717.      slope[X] = end[X] - start[X];
  718.      slope[Y] = end[Y] - start[Y];
  719.      slope[Z] = end[Z] - start[Z];
  720.      
  721.      p = - ( obj1->normal[X] * start[X] + obj1->normal[Y] * start[Y] + obj1->normal[Z] * start[Z] + obj1->directed_distance ) /
  722.       ( obj1->normal[X] * slope[X] + obj1->normal[Y] * slope[Y] + obj1->normal[Z] * slope[Z] );
  723.      
  724.      new[X] = p * slope[X] + start[X];
  725.      new[Y] = p * slope[Y] + start[Y];
  726.      new[Z] = p * slope[Z] + start[Z];
  727. }
  728.